package com.alibaba.csp.sentinel.dashboard.repository.metric;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricDTO;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.dashboard.repository.tdengine.MetricTdengineMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author huangjd
 * @date 2024/12/3 20:11
 */
@Component("tdengineMetricsRepository")
public class TdengineMetricsRepository implements MetricsRepository<MetricEntity>, CustomMetricsRepositroy<MetricDTO>{

    @Autowired
    private MetricTdengineMapper metricTdengineMapper;

    @Override
    public void save(MetricEntity metric) {

    }

    private void test (){
        List<MetricEntity> entities = new ArrayList<>(10000);
        for (int i = 0; i < 10000; i++) {
            MetricEntity entry = new MetricEntity();
            entry.setAppName("testSaveAll");
            entry.setResource("testResource" + i);
            entry.setTimestamp(new Date(System.currentTimeMillis()));
            entry.setPassQps(1L);
            entry.setExceptionQps(1L);
            entry.setBlockQps(0L);
            entry.setSuccessQps(1L);
            entities.add(entry);
        }
        this.saveAll(entities);
        List<String> result = this.listResourcesOfApp("testSaveAll");
        Assert.isTrue(result.size() == entities.size());
    }

    /**
     * 批量保存
     * 分批插入，如果同一批次插入的数量过多，可能会导致TDengine 报错 SQL statement too long
     */
    @Override
    public void saveAll(Iterable<MetricEntity> metrics) {
        // 每批插入的数据量
        int batchSize = 1000;
        List<MetricEntity> batch = new ArrayList<>(batchSize);
        for (MetricEntity metric : metrics) {
            //appName特殊字符处理
            metric.setAppName(metric.getAppName().replace("-", "_"));
            batch.add(metric);
            if (batch.size() >= batchSize) {
                metricTdengineMapper.saveAll(batch);
                batch.clear();
            }
        }
        if (!batch.isEmpty()) {
            metricTdengineMapper.saveAll(batch);
        }
    }

    @Override
    public List<MetricEntity> queryByAppAndResourceBetween(String app, String resource, long startTime, long endTime) {
        // 将 long 类型的时间戳转换为 String 类型
        String startTimeStr = String.valueOf(startTime);
        String endTimeStr = String.valueOf(endTime);
        return metricTdengineMapper.queryByAppAndResourceBetween(app, resource, startTimeStr, endTimeStr);
    }

    @Override
    public IPage<String> listTopResourcesOfApp(Page page, String app, String startTime, String endTime) {
        return metricTdengineMapper.listTopResourcesOfApp(page, app, startTime, endTime);
    }

    @Override
    public List<String> listResourcesOfApp(String app) {
        return metricTdengineMapper.listResourcesOfApp(app);
    }

    @Override
    public List<MetricDTO> listAllResourcesOfAppAndSort(String app, String startTime, String endTime) {
        return metricTdengineMapper.listAllResourcesOfAppAndSort(app, startTime, endTime);
    }
}
